package com.myway.service.ibe.command;

import com.myway.core.execption.IBEException;
import com.myway.dto.domain.*;
import com.myway.dto.ibe_param.*;
import com.myway.dto.ibe_param.TaxPrice;
import com.myway.dto.ibe_param.TicketPrice;
import com.myway.dto.order.DTOPassenger;
import com.myway.dto.order.DTOPnr;
import com.myway.dto.util.CnToSpellNew;
import com.myway.dto.vo.FlyOrderVo;
import com.myway.dto.vo.FlyPassengeVo;
import com.myway.dto.vo.FlyPnrVo;
import com.myway.dto.vo.FlySegmentVo;
import com.myway.pojo.FlyOrder;
import com.myway.pojo.FlyPassenge;
import com.myway.service.ibe.ReservePNRCommandService;
import com.travelsky.ibe.client.pnr.*;
import com.travelsky.util.QDateTime;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;

import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.travelsky.ibe.client.pnr.BookPassenger.PASSENGER_ADULT;
import static com.travelsky.ibe.client.pnr.BookPassenger.PASSENGER_CHILD;

/**
 * Created by Administrator on 2018/1/15.
 * 散客PNR预定
 */
@Slf4j
public class ReservePNRCommand extends BaseIBECommand implements ReservePNRCommandService{
    @Value("${isOpenIBE}")
    private boolean isOpenIBE;

    public Map<String,Object> execute(Map<String, Object> params) {

        TicketResult ticketResult = new TicketResult();

        try {
            SellSeat ss = new SellSeat();
            //连接IBE系统669-2100005942
            this.configIBEClient(ss);
            Date dateLimit=null;
            dateLimit = new Date(new Date().getTime()+45*60*1000);
            //获取旅客航段
            List<FlySegmentVo> segments = (List<FlySegmentVo>) params.get("segments");
            //获取旅客
            List<FlyPassengeVo> passenges = (List<FlyPassengeVo>) params.get("passenges");
            FlyOrderVo flyOrder = (FlyOrderVo) params.get("order");
            //票价税费
//            TicketPrice ticketPrice = (TicketPrice) params.get("ticketPrice");
            TotalFlyPrice totalFlyPrice = (TotalFlyPrice) params.get("totalFlyPrice");
            List<TaxPrice> taxPrices = (List<TaxPrice>) params.get("taxPrices");
            //判断乘客是否为儿童
            boolean childPasseger = passenges.size() > 0 && passenges.get(0).getPassageType().equals(PassengerType.CHILD);
            //添加航段组
            //String deadtime = "";
            // 承运人
            String airlineCode = "MJ";
            /*for (FlySegmentVo seg : segments) {
                airlineCode = seg.getAirlineCode().toUpperCase();
                break;
            }*/
            Collections.sort(segments);//按日期排序
            for (FlySegmentVo segment : segments) {
                BookAirSeg airSeg = new BookAirSeg();
                String departureTime=QDateTime.dateToString(segment.getDepTime(),"yyyy-MM-dd");
                airSeg = new BookAirSeg(segment.getFlightNo(),
                        segment.getCabinClass().charAt(0),
                        segment.getDepCode(), segment.getArrCode(),
                        ACTION_CODE_HK, 1,departureTime );
                ss.addAirSeg(airSeg);
                if(airSeg.getDepartureTime() != null && airSeg.getDepartureTime().before(dateLimit)){
                    dateLimit= airSeg.getDepartureTime();
                }
            }
            //添加乘客组
            int bxl_count = 0;

            boolean infant = false;
            for (FlyPassengeVo passenger : passenges) {
                bxl_count++;
                /*String name=passenger.getXingE()+"/"+passenger.getMingE();
                if(name.length()>28){
                    name=name.substring(0,28);
                }*/
                String name=formatName(passenger.getXingE(),passenger.getMingE());
                name=name.toUpperCase();
                ss.addPassenger(new BookPassenger(name, Integer.parseInt(passenger.getPassageType())==1?PASSENGER_ADULT:PASSENGER_CHILD, 0));
                //身份证件类型 NI身份证，CC信用卡，PP护照
                //ss.addSSR_FOID(OfficeInfo.AIRLINE,passenger.getCardType().equals(CardType.CARDN)?CardType.CARDN:CardType.CARDP , passenger.getCardNo(), passenger.getName());
                ss.addSSR_FOID(OfficeInfo.AIRLINE, CardType.CARDN, passenger.getCardNo(), name);
                //如果乘客为儿童
                if (childPasseger) {
                    String serviceinfo=(passenger.getPassgeBirth()==null?"":QDateTime.dateToString(passenger.getPassgeBirth(), "ddmmmyy"));
                    BookSSR bookssr = new BookSSR("CHLD", OfficeInfo.AIRLINE, "hk", 1, "", "", ' ', "", serviceinfo, name);
                    ss.addSSR(bookssr);
                    //添加成人备注
                    FlyPassengeVo accompaniedBy=passenger.getAccompaniedByPassenger();
                    if(accompaniedBy!=null){

                    }
                }
                if (passenger.getMoblePhone() != null) {
                    if(passenger.getPassageType().equals(PassengerType.ADULT.toString()))ss.addOSI(OfficeInfo.AIRLINE, "MJ CTCM" + passenger.getMoblePhone().replace(" ","").replace("+","") + "/P" + bxl_count);
                }
                // Add accomany infant....
                if (CollectionUtils.isNotEmpty(passenger.getAccompanyingPassengerList())) {
                    // Add Infant....
                    for (FlyPassengeVo infantPass : passenger.getAccompanyingPassengerList()) {
                        if (infantPass.getPassageType().equals(PassengerType.INFANT)) {
                            infant = true;
                            /*String infantName=CnToSpellNew.getPinYin(infantPass.getXingE())+"/"+CnToSpellNew.getPinYin(infantPass.getMingE());
                            if(infantName.length()>28){
                                infantName=infantName.substring(0,28);
                            }*/
                            String infantName = formatName(infantPass.getXingE(),infantPass.getMingE());
                            infantName=infantName.toUpperCase();
                            //如果携带婴儿，因为婴儿不占座，所以不需要添加姓名组信息，只需要在成人PNR中添加另外的婴儿信息组
                            ss.addInfant(infantPass.getPassgeBirth(), name,infantName);
                            for (FlySegmentVo segment : segments) {
                                if(!(segment.getCabinState()!=null&&segment.getCabinState().equals("SA"))) {//非信息航段
                                    ss.addSSR_INFT(OfficeInfo.AIRLINE, segment.getDepCode() + segment.getArrCode(), segment.getFlightNo().substring(2),
                                            segment.getCabinClass(), QDateTime.dateToString(segment.getDepTime(), "ddmmmyy"),infantName,
                                            QDateTime.dateToString(infantPass.getPassgeBirth(), "ddmmmyy"), "", name);
                                }
                            }
                        }
                    }
                }

            }
            flyOrder.setContactMoble(flyOrder.getContactMoble().trim().replace(" ","").replace("+",""));
            //添加联系组
            BookContact bookContact = new BookContact();
            bookContact.setpsgrName(flyOrder.getContactName());
            bookContact.setCity(flyOrder.getContactAddress());
            bookContact.setContact(flyOrder.getContactMoble());
//            String contact = (String) params.get("contact");
            String contact = flyOrder.getContactMoble()!=null?flyOrder.getContactMoble():flyOrder.getContactTel();
            ss.addContact(new BookContact(contact));
            //添加Pnr出票时限,设置出票时限为订票时间+30分钟
            if(flyOrder.getTimeLimit()!=null){
//                dateLimit=flyOrder.getTimeLimit();
            }
            ss.setTimelimit(QDateTime.dateToString(dateLimit,"yyyy-MM-dd HH:mi:ss"));
            //添加其他服务信息组OSI,不添加此项PNR无法封口
            //联系人用OSI GS CTCT 手机号，乘机人用OSI GS CTCM 手机号
            BookOSI bookOSI = new BookOSI("MJ", "CTCT" + flyOrder.getContactMoble().replace(" ","").replace("+",""));
            ss.addOSI(bookOSI);
            //加入FN组(票价组)
            /**
             * FCNT：首次出票的票面价格、
             * SCNY：客票的实际销售价格、
             * XCNY：基建+燃油、
             * ACNY：票价+基建+燃油的总和
             */
            /**
             * FN/FCNY10.00/SCNY10.00/C3.00/XCNY110.00/TCNY50.00CN/TCNY60.00YQ/ACNY120.00
             * FN/IN/FCNY10.00/SCNY10.00/C3.00/TCNYEXEMPTCN/TEXEMPTYQ/ACNY10.00/P1
             * FN:前缀FN
             * IN:如果使用了婴儿选项要加IN
             * FCNY10.00：票面价格(总价)
             * SCNY10.00/C3.00：如果开通了结算功能，SCNY10.00：实际价格，C3.00：代理费率*100.00
             * CNY110.00: 基建+燃油
             * TEXEMPTCN：豁免机场建设费，
             */
            //国内 FN/M/FCNY600.00/XCNY190.00/TCNY50.00CN/TCNY140.00YQ/ACNY790.00
            //﻿国际 FN/FCNY8820.00/SCNY8820.00/C7.00/XCNY330.00/TXYCNY50.00US/TYCCNY50.00US/﻿TXTCNY230. 00US/ACNY9150.00
            //税费设置，航信主机规定：当税费项超过3项时，第三项以后的税费航信主机对于PNR中税项的录入的要求是这样的：
            //不超过3项，录入在FN中，
            //超过3项，前面两个录入到FN中，FN中第三税为XT，值为其他的值之和。把XT的拆分写在FC的XT字段里。
            //假定税为AA AB AC AD，AE,税值为100/200/300                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         /400/豁免,均为CNY
            //FN：....../TCNY100.00AA/TCNY200.00AB/TCNY700.00XT
            //FC：....../XT CNY300.00AC CNY400.00AD EXEMPTAE
            //FC/M/TSN GS ULN 2000.00Y CNY2000.00END ROE0.6530 XT CNY179.00XACNY200.00YR
            //FN/M/FCNY2000.00/XCNY569.00/TCNY50.00CN/TCNY140.00YQ/TCNY379.00XT/ACNY2569.00
            /**
             * BookFC, BookFP的用法基本一样,只要把FN串改成FC串(eg,FC/PEK CA CAN 1300.00F CNY1300.00END或者FP串(eg.FP/CASH,CNY)就可以.
             */
            // BookFN bookFN = new BookFN();
            String fn = com.myway.service.ibe.common.PNRFN.toStringFN(totalFlyPrice,taxPrices, segments,false,childPasseger);
            ss.addFN(fn);
            if (infant) {
                String fnInf = com.myway.service.ibe.common.PNRFN.toStringFN(totalFlyPrice,taxPrices,segments, infant,false);
                ss.addFN(fnInf);
            }
            log.info(fn);
            //加入FC组(票价计算组)
            String fc = com.myway.service.ibe.common.PNRFC.toStringFC(totalFlyPrice,taxPrices, segments, false,childPasseger);
            ss.addFC(fc);
            if (infant) {
                String fcInf = com.myway.service.ibe.common.PNRFC.toStringFC(totalFlyPrice,taxPrices, segments, infant,false);
                ss.addFC(fcInf);
            }
            log.info(fc);

           //加入FP组(付款方式组)
            BookFP bookFP = new BookFP();
            String fp = "FP/CASH"
                    +","+flyOrder.getCurrency()
//                    +","+ticketPrice.getEquivFareCurrentyCode()
                    ;
            bookFP.setFp(fp);
            ss.addFP(bookFP);
            //封口Pnr
            SSResult ssResult=null;
            String pnrNo="";
            if(isOpenIBE){
                //完成PNR必须信息输入递交主机，生成PNR
                int tryNumber = 0;
                while (tryNumber < 3){
                    try{
                        ssResult = ss.commit1();
                        break;
                    }catch (Exception e){
                        tryNumber++;
                        if(tryNumber==3) throw new Exception(e);
                    }
                }
                //获取PnrNO；
                pnrNo = ssResult.getPnrno();
            }else{
                pnrNo="99999"+(int)(Math.random()*10);
            }
            // 使用此返回值。
            params.put("PNRNo", pnrNo);

            //记录IBE操作日志
//            sendLogToSave(ibeETDZLog,"RESERVEPNR,PNRNo:" + pnr.getPnrNo(),pnr);
            FlyPnrVo pnr=new FlyPnrVo();
            pnr.setPnrNo(pnrNo);
            //添加旅客、pnr关系
            insertPnrNOTOPax(passenges,pnr,ssResult);
            //检查航段状态是否为HK
            /**
             * NN，表示提出申请需要占座
             * HK，KL，KK，TK，DK，表示占座成功。
             * RR，表示已经出票或者即将出票
             */
            if(isOpenIBE){
                boolean pnrFlag = checkAllSegmentHK(ssResult,segments);
                boolean inftFlag = checkInftStatus(pnrNo,passenges);
                if (pnrFlag || inftFlag) {
                    // pnr 中存在非HK航段，清理该PNR，并且异常抛出，取消订单生成
                    PnrManage manage = new PnrManage();
                    this.configIBEClient(manage);
                    String res = null;
                    try {
                        res = manage.deletePnr(pnrNo);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    log.info(" Not expected pnr status , cancel pnr["+pnr.getPnrNo()+"], cancel order["+flyOrder.getOrderId()+"]...");
                    throw new Exception(" 订单生成失败，你选择的舱位价格可能已不存在，请重新提交订单...");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new IBEException(e.getMessage(),e);
        }
        return params;
    }

    /*
    /**
     * 为旅客(DTOPassenger)添加PNR信息
     * @param passengerList
     * @param pnr
     * @param result
     */
    private void insertPnrNOTOPax(List<FlyPassengeVo> passengerList, FlyPnrVo pnr, SSResult result) {
        // set pnr back to pax...
        for (FlyPassengeVo pas : passengerList) {
            pas.setPnr(pnr);

            if (CollectionUtils.isNotEmpty(pas.getAccompanyingPassengerList())) {
                // Set PNR to accompanying passengers (infant)
                for (FlyPassengeVo ap : pas.getAccompanyingPassengerList()) {
                    ap.setPnr(pnr);
            }
            }
        }
    }

    /**
     * 检查所有航段状态是否为HK
     *
     * @param result
     * @param segments
     */
    private boolean checkAllSegmentHK(SSResult result, List<FlySegmentVo> segments) {
        boolean pnrFlag = false;
        for (FlySegmentVo ps : segments) {
            for (int i = 0; i < result.getSegmentsCount() && !pnrFlag; i++) {
                SSSegment sg = result.getSegmentAt(i);
                // check segment action code......
                if (sg.getAirNo().equalsIgnoreCase(ps.getFlightNo())
                        && sg.getOrgCity().equalsIgnoreCase(ps.getDepCode())
                        && sg.getDesCity().equalsIgnoreCase(ps.getArrCode())) {
                    // 此处异常抛出，导致往返程编码存在虚耗情况，订单无法生成，但编码已预订,修改
                    if (!"HK".equalsIgnoreCase(sg.getActionCode())) {
                        log.info(" pnr status is " + sg.getActionCode() + ", not HK");
                        log.info(" cancel this pnr  " + result.getPnrno());
                        pnrFlag = true;
                    }
                    break;
                }
            }
        }
        return pnrFlag;
    }

    /**
     * 检查带婴儿PNR中婴儿的SSR INFT项状态是否为KK或HK，如果不是则预订失败，并取消编码。
     *
     * @param pnrNo
     * @param passenges
     * @return
     */
    private boolean checkInftStatus(String pnrNo, List<FlyPassengeVo> passenges) {
        boolean inftFlag = false;
        for (FlyPassengeVo passenge : passenges) {
            if (CollectionUtils.isNotEmpty(passenge.getAccompanyingPassengerList())) {
                RT rt = new RT();
                this.configIBEClient(rt);
                RTResult rtResult = null;
                boolean flag = false;
                int i = 3;
                while (!flag && i > 0) {
                    try {
                        rtResult = rt.retrieve(pnrNo);
                        if (rtResult != null) {
                            flag = true;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    i = i - 1;
                }
                for (int j = 0; j < rtResult.getSSRsCount(); j++) {
                    String ssrType = rtResult.getSSRAt(j).getSSRType();
                    String actionCode = rtResult.getSSRAt(j).getActionCode();
                    if (ssrType.equals("INFT")) {
                        if (!actionCode.equals("KK") && !actionCode.equals("HK")) {
                            inftFlag = true;
                            log.info(" INFT status is " + actionCode + ", not HK or KK");
                            log.info(" cancel this INFT pnr  " + pnrNo);
                        }
                    }
                }
            }
        }
        return inftFlag;

    }

    /**
     * 出票
     *
     * @param pnr
     */
    public String etdz(String pnr) {
        ETDZ etdz = new ETDZ();
        this.configIBEClient(etdz);
        //issueTicket(java.lang.String pnrno,int printerNo)pnrno(PNR编号),printerNo（打票机编号）
        try {
            String result = etdz.issueTicket(pnr, 2);
            System.out.println(etdz.issueTicket(pnr, 2));//返回OK
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    private String formatName(String xing,String ming){
        String name = "";
        if (xing.length()>26&&ming.length()>26){
            name = xing.substring(0,20)+"/"+ming.substring(0,7);
         }else if(xing.length()>26){
            name = xing.substring(0,(27-ming.length()))+"/"+ming;
         }else if(ming.length()>26){
            name = xing+"/"+ming.substring(0,(27-xing.length()));
         }else{
            name=xing+"/"+ming;
         }
        return name;
    }
}
